package org.jasig.cas.client.util;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

import javax.net.ssl.HostnameVerifier;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.jasig.cas.client.authentication.sdk.ApiCaller;
import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
import org.jasig.cas.client.ssl.HttpsURLConnectionFactory;

/**
 * 用于初始化ApiSdk的环境，使用api进行CAS Server认证必须启用此filter
 * 
 * @author CreGu
 *
 */
public class ApiSdkFilter extends AbstractConfigurationFilter {

	public void destroy() {

	}

	public void doFilter(ServletRequest servletRequest,
			ServletResponse servletResponse, FilterChain filterChain)
			throws IOException, ServletException {
		filterChain.doFilter(servletRequest, servletResponse);
	}

	/**
	 * Gets the ssl config to use for HTTPS connections if one is configured for
	 * this filter.
	 * 
	 * @param filterConfig
	 *            Servlet filter configuration.
	 * @return Properties that can contains key/trust info for Client Side
	 *         Certificates
	 */
	protected Properties getSSLConfig(final FilterConfig filterConfig) {
		final Properties properties = new Properties();
		final String fileName = getPropertyFromInitParams(filterConfig,
				"sslConfigFile", null);

		if (fileName != null) {
			FileInputStream fis = null;
			try {
				fis = new FileInputStream(fileName);
				properties.load(fis);
				logger.trace("Loaded {} entries from {}", properties.size(),
						fileName);
			} catch (final IOException ioe) {
				logger.error(ioe.getMessage(), ioe);
			} finally {
				CommonUtils.closeQuietly(fis);
			}
		}
		return properties;
	}

	/**
	 * Gets the configured {@link HostnameVerifier} to use for HTTPS connections
	 * if one is configured for this filter.
	 * 
	 * @param filterConfig
	 *            Servlet filter configuration.
	 * @return Instance of specified host name verifier or null if none
	 *         specified.
	 */
	protected HostnameVerifier getHostnameVerifier(
			final FilterConfig filterConfig) {
		final String className = getPropertyFromInitParams(filterConfig,
				"hostnameVerifier", null);
		logger.trace("Using hostnameVerifier parameter: {}", className);
		final String config = getPropertyFromInitParams(filterConfig,
				"hostnameVerifierConfig", null);
		logger.trace("Using hostnameVerifierConfig parameter: {}", config);
		if (className != null) {
			if (config != null) {
				return ReflectUtils.newInstance(className, config);
			} else {
				return ReflectUtils.newInstance(className);
			}
		}
		return null;
	}

	public void init(FilterConfig filterConfig) throws ServletException {
		final String casServerUrlPrefix = getPropertyFromInitParams(
				filterConfig, "casServerUrlPrefix", null);
		final String serverUrl = getPropertyFromInitParams(filterConfig,
				"serverUrl", null);

		CommonUtils.assertNotNull(casServerUrlPrefix,
				"casServerUrlPrefix cannot be null.");
		CommonUtils.assertNotNull(casServerUrlPrefix,
				"serverUrl cannot be null.");

		final HttpURLConnectionFactory factory = new HttpsURLConnectionFactory(
				getHostnameVerifier(filterConfig), getSSLConfig(filterConfig));

		ApiCaller.newInstance(casServerUrlPrefix, serverUrl, factory);
	}
}
